home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 112 / EnigmaAmiga112CD.iso / dalla rivista / news / orbit / source / sound_amiga.c < prev    next >
C/C++ Source or Header  |  2000-05-01  |  6KB  |  257 lines

  1. /*
  2.     Load and convert a WAV file, play it with 'ahi.device'
  3.  
  4.     Written by Oliver Gantert
  5.  
  6.     31.04.2000 - Yeah, this works!
  7. */
  8.  
  9. #include "orbit.h"
  10. #include <devices/ahi.h>
  11. #include <clib/ahi_protos.h>
  12. #include <stdio.h>
  13.  
  14. struct RIFF_Header
  15. {
  16.   ULONG ChunkID;          /*  must be 0x52494646  */
  17.   ULONG ChunkSize;        /*  little endian!  */
  18.   ULONG Format;           /*  must be 0x57415645  */
  19.   ULONG Subchunk1ID;      /*  must be 0x666d7420  */
  20.   ULONG Subchunk1Size;    /*  little endian, must be 16  */
  21.   UWORD AudioFormat;      /*  little endian, must be 1  */
  22.   UWORD NumChannels;      /*  little endian, Mono = 1, Stereo = 2  */
  23.   ULONG SampleRate;       /*  little endian, 44100 etc.  */
  24.   ULONG ByteRate;         /*  little endian, == SampleRate * NumChannels * BitsPerSample/8  */
  25.   UWORD BlockAlign;       /*  little endian, == NumChannels * BitsPerSample/8  */
  26.   UWORD BitsPerSample;    /*  little endian, 8, 16, etc.  */
  27.   ULONG Subchunk2ID;      /*  must be 0x64617461  */
  28.   ULONG Subchunk2Size;    /*  little endian, == NumSamples * NumChannels * BitsPerSample/8  */
  29. };
  30.  
  31. struct ASample
  32. {
  33.   ULONG SampleRate;
  34.   ULONG Size;
  35.   UBYTE *SampleData;
  36.   ULONG Type;
  37. };
  38.  
  39. struct MsgPort *AHImp = NULL;
  40. struct AHIRequest *AHIio = NULL;
  41. struct ASample *smp[3] = {NULL, NULL, NULL};
  42. ULONG ahi_available = 0,
  43.       ahi_open = 0;
  44.  
  45. UWORD ChangeEndianW(UWORD wert)
  46. {
  47.   UBYTE t;
  48.   union
  49.   {
  50.     UBYTE c[2];
  51.     UWORD w;
  52.   } u;
  53.  
  54.   u.w = wert;
  55.   t = u.c[0];
  56.   u.c[0] = u.c[1];
  57.   u.c[1] = t;
  58.  
  59.   return(u.w);
  60. }
  61.  
  62. ULONG ChangeEndianL(ULONG wert)
  63. {
  64.   UBYTE t;
  65.   union
  66.   {
  67.     UBYTE c[4];
  68.     ULONG w;
  69.   } u;
  70.  
  71.   u.w = wert;
  72.   t = u.c[0];
  73.   u.c[0] = u.c[3];
  74.   u.c[3] = t;
  75.   t = u.c[1];
  76.   u.c[1] = u.c[2];
  77.   u.c[2] = t;
  78.  
  79.   return(u.w);
  80. }
  81.  
  82. struct ASample *LoadWAVSample(STRPTR filename)
  83. {
  84.   struct ASample *smp = NULL;
  85.   struct RIFF_Header *riff;
  86.   FILE *file;
  87.   UWORD *smpdata;
  88.   ULONG i;
  89.  
  90.   if (file = fopen(filename, "rb"))
  91.   {
  92.     if (riff = (struct RIFF_Header *)malloc(sizeof(struct RIFF_Header)))
  93.     {
  94.       fread(riff, sizeof(struct RIFF_Header), 1, file);
  95.       /*
  96.           Check if it's a standard RIFF WAVE file.
  97.       */
  98.       if ((riff->ChunkID      == 0x52494646) && (riff->Format       == 0x57415645) &&
  99.           (riff->Subchunk1ID  == 0x666d7420) && (riff->Subchunk2ID  == 0x64617461))
  100.       {
  101.         riff->Subchunk1Size = ChangeEndianL(riff->Subchunk1Size);
  102.         riff->AudioFormat   = ChangeEndianW(riff->AudioFormat);
  103.         riff->NumChannels   = ChangeEndianW(riff->NumChannels);
  104.         riff->SampleRate    = ChangeEndianL(riff->SampleRate);
  105.         riff->BitsPerSample = ChangeEndianW(riff->BitsPerSample);
  106.         riff->Subchunk2Size = ChangeEndianL(riff->Subchunk2Size);
  107.         /*
  108.             More checks.
  109.         */
  110.         if ((riff->Subchunk1Size == 16) && (riff->AudioFormat == 1))
  111.         {
  112.           if (smp = (struct ASample *)malloc(sizeof(struct ASample)))
  113.           {
  114.             smp->SampleRate    = riff->SampleRate;
  115.             smp->Size          = riff->Subchunk2Size;
  116.             if (riff->NumChannels == 1)
  117.             {
  118.               if (riff->BitsPerSample == 8)
  119.                 smp->Type = AHIST_M8S;
  120.               else
  121.                 smp->Type = AHIST_M16S;
  122.             }
  123.             else
  124.             {
  125.               if (riff->BitsPerSample == 8)
  126.                 smp->Type = AHIST_S8S;
  127.               else
  128.                 smp->Type = AHIST_S16S;
  129.             }
  130.             if (smp->SampleData = (UBYTE *)malloc(smp->Size))
  131.             {
  132.               fread(smp->SampleData, smp->Size, 1, file);
  133.               /*
  134.                   Change endian of 16bit data
  135.               */
  136.               if (riff->BitsPerSample > 8)
  137.               {
  138.                 smpdata = (UWORD *)smp->SampleData;
  139.                 for (i = 0; i < (smp->Size>>1); i++)
  140.                 {
  141.                   smpdata[i] = ChangeEndianW(smpdata[i]);
  142.                 }
  143.               }
  144.             }
  145.             else
  146.             {
  147.               free(smp);
  148.               smp = NULL;
  149.             }
  150.           }
  151.         }
  152.       }
  153.       free(riff);
  154.     }
  155.     fclose(file);
  156.   }
  157.   return(smp);
  158. }
  159.  
  160. VOID FreeASample(struct ASample *smp)
  161. {
  162.   if (smp)
  163.   {
  164.     if (smp->SampleData)
  165.       free(smp->SampleData);
  166.     free(smp);
  167.   }
  168. }
  169.  
  170. /*
  171.     ==============
  172.     THE ORBIT PART
  173.     ==============
  174. */
  175.  
  176. int InitSound()
  177. {
  178.   if (AHImp = (struct MsgPort *)CreateMsgPort())
  179.   {
  180.     if (AHIio = (struct AHIRequest *)CreateIORequest(AHImp, sizeof(struct AHIRequest)))
  181.     {
  182.       AHIio->ahir_Version = 4;
  183.       if (!OpenDevice(AHINAME, 0, (struct IORequest *)AHIio, 0))
  184.       {
  185.         ahi_open = 1;
  186.         if (smp[0] = LoadWAVSample("sounds/phaser.wav"))
  187.         {
  188.           if (smp[1] = LoadWAVSample("sounds/explosion1.wav"))
  189.           {
  190.             if (smp[2] = LoadWAVSample("sounds/communicator.wav"))
  191.             {
  192.               AHIio->ahir_Std.io_Message.mn_Node.ln_Pri = 0;
  193.               AHIio->ahir_Std.io_Command  = CMD_WRITE;
  194.               AHIio->ahir_Std.io_Offset   = 0;
  195.               AHIio->ahir_Volume          = 0x10000;
  196.               AHIio->ahir_Position        = 0x8000;
  197.               AHIio->ahir_Link            = NULL;
  198.               ahi_available = 1;
  199.               return(1);
  200.             }
  201.             FreeASample(smp[1]);
  202.           }
  203.           FreeASample(smp[0]);
  204.         }
  205.         CloseDevice((struct IORequest *)AHIio);
  206.       }
  207.       DeleteIORequest((struct IORequest *)AHIio);
  208.     }
  209.     DeleteMsgPort(AHImp);
  210.   }
  211.   return(0);
  212. }
  213.  
  214. int PlayAudio(enum sounds nSound)
  215. {
  216.   if (ahi_available)
  217.   {
  218.     AHIio->ahir_Std.io_Data     = smp[nSound]->SampleData;
  219.     AHIio->ahir_Std.io_Length   = smp[nSound]->Size;
  220.     AHIio->ahir_Frequency       = smp[nSound]->SampleRate;
  221.     AHIio->ahir_Type            = smp[nSound]->Type;
  222.     SendIO((struct IORequest *)AHIio);
  223.     return(1);
  224.   }
  225.   return(0);
  226. }
  227.  
  228. void FinishSound()
  229. {
  230.   if (ahi_available)
  231.   {
  232.     WaitIO((struct IORequest *)AHIio);
  233.     ahi_available = 0;
  234.   }
  235.   if (AHIio)
  236.   {
  237.     if (ahi_open)
  238.     {
  239.       CloseDevice((struct IORequest *)AHIio);
  240.       ahi_open = 0;
  241.     }
  242.     DeleteIORequest((struct IORequest *)AHIio);
  243.     AHIio = NULL;
  244.   }
  245.   if (AHImp)
  246.   {
  247.     DeleteMsgPort(AHImp);
  248.     AHImp = NULL;
  249.   }
  250.   if (smp[0])
  251.     FreeASample(smp[0]);
  252.   if (smp[1])
  253.     FreeASample(smp[1]);
  254.   if (smp[2])
  255.     FreeASample(smp[2]);
  256. }
  257.